package org.xwalk.core.internal;

import android.util.Log;
import java.security.cert.CertificateEncodingException;
import java.security.cert.X509Certificate;
import java.security.Principal;
import java.security.PrivateKey;
import java.util.List;

import java.lang.reflect.Constructor;
import java.lang.reflect.Method;

public class ClientCertRequestHandlerBridge extends ClientCertRequestHandlerInternal {
    private XWalkCoreBridge coreBridge;
    private Object wrapper;

    public Object getWrapper() {
        return wrapper;
    }


    private ClientCertRequestHandlerInternal internal;

    ClientCertRequestHandlerBridge(ClientCertRequestHandlerInternal internal) {
        this.internal = internal;
        reflectionInit();
    }

    @Override
    public void proceed(final PrivateKey privateKey, final List<X509Certificate> chain) {
        if (proceedPrivateKeyListMethod == null || proceedPrivateKeyListMethod.isNull()) {
            proceedSuper(privateKey, chain);
        } else {
            proceedPrivateKeyListMethod.invoke(privateKey, chain);
        }
    }

    public void proceedSuper(final PrivateKey privateKey, final List<X509Certificate> chain) {
        if (internal == null) {
            super.proceed(privateKey, chain);
        } else {
            internal.proceed(privateKey, chain);
        }
    }

    private ReflectMethod proceedPrivateKeyListMethod = new ReflectMethod(null, "proceed");

    @Override
    public void ignore() {
        if (ignoreMethod == null || ignoreMethod.isNull()) {
            ignoreSuper();
        } else {
            ignoreMethod.invoke();
        }
    }

    public void ignoreSuper() {
        if (internal == null) {
            super.ignore();
        } else {
            internal.ignore();
        }
    }

    private ReflectMethod ignoreMethod = new ReflectMethod(null, "ignore");

    @Override
    public void cancel() {
        if (cancelMethod == null || cancelMethod.isNull()) {
            cancelSuper();
        } else {
            cancelMethod.invoke();
        }
    }

    public void cancelSuper() {
        if (internal == null) {
            super.cancel();
        } else {
            internal.cancel();
        }
    }

    private ReflectMethod cancelMethod = new ReflectMethod(null, "cancel");

    @Override
    public String getHost() {
        if (getHostMethod == null || getHostMethod.isNull()) {
            return getHostSuper();
        } else {
            return (String)getHostMethod.invoke();
        }
    }

    public String getHostSuper() {
        String ret;
        if (internal == null) {
            ret = super.getHost();
        } else {
            ret = internal.getHost();
        }
        if (ret == null) return null;
        return ret;
    }

    private ReflectMethod getHostMethod = new ReflectMethod(null, "getHost");

    @Override
    public int getPort() {
        if (getPortMethod == null || getPortMethod.isNull()) {
            return getPortSuper();
        } else {
            return (Integer)getPortMethod.invoke();
        }
    }

    public int getPortSuper() {
        int ret;
        if (internal == null) {
            ret = super.getPort();
        } else {
            ret = internal.getPort();
        }
        
        return ret;
    }

    private ReflectMethod getPortMethod = new ReflectMethod(null, "getPort");

    @Override
    public String[] getKeyTypes() {
        if (getKeyTypesMethod == null || getKeyTypesMethod.isNull()) {
            return getKeyTypesSuper();
        } else {
            return (String[])getKeyTypesMethod.invoke();
        }
    }

    public String[] getKeyTypesSuper() {
        String[] ret;
        if (internal == null) {
            ret = super.getKeyTypes();
        } else {
            ret = internal.getKeyTypes();
        }
        if (ret == null) return null;
        return ret;
    }

    private ReflectMethod getKeyTypesMethod = new ReflectMethod(null, "getKeyTypes");

    @Override
    public Principal[] getPrincipals() {
        if (getPrincipalsMethod == null || getPrincipalsMethod.isNull()) {
            return getPrincipalsSuper();
        } else {
            return (Principal[])getPrincipalsMethod.invoke();
        }
    }

    public Principal[] getPrincipalsSuper() {
        Principal[] ret;
        if (internal == null) {
            ret = super.getPrincipals();
        } else {
            ret = internal.getPrincipals();
        }
        if (ret == null) return null;
        return ret;
    }

    private ReflectMethod getPrincipalsMethod = new ReflectMethod(null, "getPrincipals");


    void reflectionInit() {
        coreBridge = XWalkCoreBridge.getInstance();
        if (coreBridge == null) return;

        ReflectConstructor constructor = new ReflectConstructor(
                coreBridge.getWrapperClass("ClientCertRequestHandler"), Object.class);
        try {
            wrapper = constructor.newInstance(this);
        } catch (UnsupportedOperationException e) {
            return;
        }

        proceedPrivateKeyListMethod.init(wrapper, null,
                "proceed", PrivateKey.class, List.class);
        ignoreMethod.init(wrapper, null,
                "ignore");
        cancelMethod.init(wrapper, null,
                "cancel");
        getHostMethod.init(wrapper, null,
                "getHost");
        getPortMethod.init(wrapper, null,
                "getPort");
        getKeyTypesMethod.init(wrapper, null,
                "getKeyTypes");
        getPrincipalsMethod.init(wrapper, null,
                "getPrincipals");
    }
}
